package com.xz.knowledgeDuplication.thread.advice;

/**
 * 生产者/消费者 管程法
 * @author 召
 * @date 2022-07-27 21:14:06
 */
public class ProducerCustomer {

    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        new Thread(new Producer(buffer)).start();
        new Thread(new Customer(buffer)).start();
    }
}

/**
 * 生产者
 */
class Producer implements Runnable {

    /**
     * 缓冲区
     */
    private Buffer buffer;

    public Producer(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            buffer.push(new Product(i + 1));
        }
    }
}

/**
 * 消费者
 */
class Customer implements Runnable {

    /**
     * 缓冲区
     */
    private Buffer buffer;

    public Customer(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("消费第" + buffer.pop().getI() + "件商品 --- ");
        }
    }
}

/**
 * 商品
 */
class Product {

    private int i;

    public Product(int i) {
        this.i = i;
    }

    public int getI() {
        return i;
    }

}

/**
 * 缓冲区
 */
class Buffer {

    /**
     * 商品
     */
    private Product[] products = new Product[10];

    /**
     * 数量
     */
    private int count = 0;

    /**
     * 放入
     */
    public synchronized void push(Product product) {
        if (count == 10) {
            try {
                // 容器满了停止生产
                this.wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 放入商品
        this.products[count++] = product;
        System.out.println("生产第" + product.getI() + "件商品");
        // 通知消费
        this.notifyAll();
    }

    /**
     * 取出
     *
     * @return 商品
     */
    public synchronized Product pop() {
        if (count == 0) {
            // 容器为空停止消费
            try {
                this.wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 放入商品
        Product product = this.products[--count];
        // 通知生产
        this.notifyAll();
        return product;
    }
}